package okw.database;

import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.hibernate.exception.ConstraintViolationException;

import core.modules.LoggerModule;
import core.modules.configuration.ConfigurationManager;
import core.modules.database.corebase.AdministratorTokenCore;
import core.modules.database.corebase.ElectionCore;
import core.modules.database.corebase.ElectionData;
import core.modules.database.corebase.OKWElectionResultCore;
import core.modules.database.corebase.OKWMemberCore;
import core.modules.database.corebase.SummaryPackageCore;
import core.modules.database.corebase.VoteCore;
import core.modules.database.corebase.VoterCore;
import core.modules.database.corebase.VotesPackageCore;
import core.modules.database.corebase.VotingCardCore;
import core.modules.database.corebase.VotingSubcardCore;
import core.modules.database.corebase.VotingSubcardOptionCore;

import okw.gui.MainWindowO;
import okw.util.HibernateUtil;

public class DatabaseManager {
	private static DatabaseManager instance;
	private static LoggerModule logger = null;
	
	private DatabaseManager() {
		HibernateUtil.getSessionFactory().getCurrentSession();
		try {
	    	logger = new LoggerModule("okwDatabase.log", null);
	    } catch (IOException e) {
	    	e.printStackTrace();
			throw new RuntimeException("Problems with creating the log files");
	    }
		logger.getLoggerInstance().log(Level.FINE, "Start bazy danych");
	}
	
	public static DatabaseManager getInstance() {
		if (instance == null) {
			synchronized(DatabaseManager.class){
				if(instance == null)
					instance = new DatabaseManager();
			}
		}
		return instance;
	}

	public void closeDatabaseSession() {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		HibernateUtil.getSessionFactory().close();
	}

	public Long save(Object obj) {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		
		Long id = null;
		try {
			id = (Long) session.save(obj);
		} catch (ConstraintViolationException e) {
			session.getTransaction().rollback();
			e.printStackTrace();
			return null;
		}

		session.getTransaction().commit();
		return id;
	}
	
	public void update(Object obj) {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		session.update(obj);

		session.getTransaction().commit();
	}

	public <T> T get(Class<T> obj, Long id) { // przykładowe wywołanie:
												// get(OKW.class, okw.getId());
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		@SuppressWarnings("unchecked")
		T object = (T) session.get(obj.getName(), id);

		session.getTransaction().commit();
		return object;
	}

	public <T> List<T> getAll(Class<T> obj) { // przykładowe wywołanie:
												// getAll(OKW.class);
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		String querystring = "from " + obj.getSimpleName();
		Query query = session.createQuery(querystring);
		@SuppressWarnings("unchecked")
		List<T> list = query.list();

		session.getTransaction().commit();
		return list;
	}
	
	public void addVotersToElection(ArrayList<VoterCore> voterCores, Election election) {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		
		for (VoterCore voterCore : voterCores) {
			Voter voter = new Voter(voterCore.getName(), voterCore.getSurname(), voterCore.getAddress(), voterCore.getIdentificationField(), election);
			session.save(voter);
			session.update(election);
		}
		
		session.getTransaction().commit();
	}
	
	public Terminal getTerminal(String identificationField) {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		
		Terminal terminal = (Terminal) session
				.createCriteria(Terminal.class)
				.add(Restrictions.like("identificationField", identificationField)).uniqueResult();
		
		session.getTransaction().commit();
		
		if (terminal != null)
			return terminal;
		else 
			return null;
	}
	
	public void addTerminalConfigurationToTerminal(TerminalConfiguration terminalConfiguration, Terminal terminal){
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		
		TerminalConfiguration tConf = terminal.getTerminalConfiguration();
		if (tConf != null)
			session.delete(tConf);
		terminal.setTerminalConfiguration(terminalConfiguration);
		session.update(terminal);
		
		session.getTransaction().commit();
		logger.getLoggerInstance().log(Level.FINE, "Dodanie konfiguracji do Terminala: "+terminal.getIdentificationField());
	}
	
	public void addOKWMembersToElection(ArrayList<OKWMemberCore> okwMemberCores, Election election){
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		for (OKWMemberCore okwMemberCore : okwMemberCores){
			OKWMember okwMember = new OKWMember(okwMemberCore.getName(), okwMemberCore.getSurname(), okwMemberCore.getAddress(), okwMemberCore.getIdentificationField());
			session.save(okwMember);
			for (AdministratorTokenCore administratorTokenCore : okwMemberCore.getAdministratorTokens()) {
				AdministratorToken administratorToken = new AdministratorToken(administratorTokenCore.getValue());
				administratorToken.setOkwmember(okwMember);
				administratorToken.setElection(election);
				session.save(administratorToken);
				election.addToAdministratorToken(administratorToken);
				okwMember.addToAdministratorToken(administratorToken);
				session.update(administratorToken);
			}
			session.update(okwMember);
		}
		session.update(election);
		
		session.getTransaction().commit();
	}
	
	public void addVotingCardsToElection(ArrayList<VotingCardCore> votingCardCores, Election election){
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		for (VotingCardCore votingCardCore : votingCardCores){
			VotingCard votingCard = new VotingCard(votingCardCore.getName(), votingCardCore.getDescription());
			votingCard.addToElection(election);
			session.save(votingCard);
			for (VotingSubcardCore votingSubcardCore : votingCardCore.getVotingSubcards()){
				VotingSubcard votingSubcard = new VotingSubcard(votingSubcardCore.getName(), votingSubcardCore.getDescription(), votingSubcardCore.getAllowedChecks());
				votingSubcard.setVotingCard(votingCard);
				session.save(votingSubcard);
				votingCard.addToVotingSubcard(votingSubcard);
				for (VotingSubcardOptionCore votingSubcardOptionCore : votingSubcardCore.getVotingSubcardOptions()){
					VotingSubcardOption votingSubcardOption = new VotingSubcardOption(votingSubcardOptionCore.getName(), votingSubcardOptionCore.getCkwVotingSubcardOption(), votingSubcard);
					session.save(votingSubcardOption);
					session.update(votingSubcard);
				}
				session.update(votingSubcard);
			}
			session.update(votingCard);
		}
		session.update(election);
				
		session.getTransaction().commit();
	}
	
	public synchronized void saveState(State state){
		deleteTable(State.class);
		save(state);
	}
	
	public State getState(){
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		State state = (State) session
				.createCriteria(State.class).uniqueResult();
		session.getTransaction().commit();
		
		return state;
	}
	
	public boolean hasMassage(String senderIdentificationField, int messageNumber){
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		Message message = (Message) session
				.createCriteria(Message.class)
				.add(Restrictions.like("senderIdentificationField", senderIdentificationField))
				.add(Restrictions.like("messageNumber", messageNumber)).uniqueResult();
		
		session.getTransaction().commit();
		
		if (message != null)
			return true;
		return false;
	}
	
	public static void main(String[] args) {
		DatabaseManager db = DatabaseManager.getInstance();

		db.clearDatabase(true);
		
//		SummaryPackage summaryPackage = new SummaryPackage();
//		summaryPackage.setProperVotesNumber(1);
//		summaryPackage.setVotesNumber(3);
//		db.save(summaryPackage);
//		
//		OKWElectionResult okwElectionResult = new OKWElectionResult(new Long(1), 2);
//		okwElectionResult.setSummaryPackage(summaryPackage);
//		db.save(okwElectionResult);
		
		Terminal terminal = new Terminal("n1", "id1");
		db.save(terminal);
		
		db.deleteTerminal("id1");


		db.closeDatabaseSession();
	}

	public void deleteTerminal(String identificationField) {
		Terminal terminal = getTerminal(identificationField);
		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		
		try {
			TerminalConfiguration terminalConfiguration = terminal.getTerminalConfiguration();
			session.delete(terminal);
			terminalConfiguration = (TerminalConfiguration) session.get(TerminalConfiguration.class, terminalConfiguration.getId());
			session.delete(terminalConfiguration);
			ConfigurationManager cm = ConfigurationManager.getInstance();
			cm.removeConfig(terminalConfiguration.getIdentificationField());
		} catch (NullPointerException e) {
				
		}
		
		session.getTransaction().commit();
		logger.getLoggerInstance().log(Level.FINE, "Usunięcie Terminala {0} z plikem konfiguracyjnym", new Object[] {identificationField});
	}
	
	public void saveOKWConfiguration(OKWConfiguration okwConfiguration) {
		deleteTable(OKWConfiguration.class);
		save(okwConfiguration);
		logger.getLoggerInstance().log(Level.FINE, "Zapis pliku konfiguracyjnego dla OKW");
	}
	
	public OKWConfiguration getOKWConfiguration(){
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		OKWConfiguration configuration = (OKWConfiguration) session
				.createCriteria(OKWConfiguration.class).uniqueResult();
		session.getTransaction().commit();
		
		return configuration;
	}
	
	public Boolean hasOKWConfiguration(){
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		@SuppressWarnings("unchecked")
		List<OKWConfiguration> configurations = session
				.createCriteria(OKWConfiguration.class).list();
		session.getTransaction().commit();
		if (configurations.isEmpty())
			return false;
		return true;
	}
	
	public <T> void deleteTable(Class<T> obj){
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		
		String querystring = "delete from " + obj.getName();
		Query query = session.createQuery(querystring);
		query.executeUpdate();
		
		session.getTransaction().commit();
	}
	
	public void saveElectionData(ElectionData electionData){
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		Election electiontmp = (Election) session
				.createCriteria(Election.class)
				.add(Restrictions.like("name", electionData.getElection().getName())).uniqueResult();
		session.getTransaction().commit();
		
		if (electiontmp != null){
			deleteElectionData(electiontmp.getId());
		}
		
		ElectionCore electionCore = electionData.getElection();
		Election election = new Election(electionCore.getName(), electionCore.getStartDate(), electionCore.getEndDate());
		save(election);
		addVotersToElection(electionData.getVoters(), election);
		addOKWMembersToElection(electionData.getOkwMembers(), election);
		addVotingCardsToElection(electionData.getVotingCards(), election);
		logger.getLoggerInstance().log(Level.FINE, "Zapisanie danych wyborczych dla Election: "+election.getName());
	}
	
	public void deleteElectionData(Long electionId){
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		
		Election election = (Election) session.get(Election.class, electionId);
		
		Set<AdministratorToken> administratorTokens = new HashSet<AdministratorToken>(election.getAdministratorTokens());
		for (AdministratorToken administratorToken : administratorTokens){
			administratorToken.removeFromOkwmember(administratorToken.getOkwmember());
			administratorToken.removeFromElection(administratorToken.getElection());
			session.delete(administratorToken);
		}

		String querystring = "from OKWMember";
		Query query = session.createQuery(querystring);
		@SuppressWarnings("unchecked")
		List<OKWMember> list = query.list();
		List<OKWMember> okwMembers = new ArrayList<OKWMember>(list);
		for(OKWMember okwMember : okwMembers){
			if (okwMember.getAdministratorTokens().isEmpty())
				session.delete(okwMember);
		}
		
		Set<Voter> voters = new HashSet<Voter>(election.getVoters());
		for(Voter voter : voters){
			voter.removeFromElection(voter.getElection());
			session.delete(voter);
		}
		
		Set<VotingCard> votingCards = new HashSet<VotingCard>(election.getVotingCards());
		for(VotingCard votingCard : votingCards){
			Set<VotingSubcard> votingSubcards = new HashSet<VotingSubcard>(votingCard.getVotingSubcards());
			for(VotingSubcard votingSubcard : votingSubcards){
				Set<VotingSubcardOption> votingSubcardOptions = new HashSet<VotingSubcardOption>(votingSubcard.getVotingSubcardOptions());
				for(VotingSubcardOption votingSubcardOption : votingSubcardOptions){
					votingSubcardOption.removeFromVotingSubcard(votingSubcardOption.getVotingSubcard());
					session.delete(votingSubcardOption);
				}
				votingSubcard.removeFromVotingCard(votingSubcard.getVotingCard());
				session.delete(votingSubcard);
			}
			votingCard.removeFromElection(votingCard.getElection());
			session.delete(votingCard);
		}
		session.delete(election);
		
		session.getTransaction().commit();
	}
	
	public void deleteElection(String electionName) {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		Election election = (Election) session
				.createCriteria(Election.class)
				.add(Restrictions.like("name", electionName)).uniqueResult();
		ArrayList<VotesPackage> votesPackages = new ArrayList<VotesPackage>();
		VotesPackage votesPackage;
		Set<VotingCard> votingCards = new HashSet<VotingCard>(election.getVotingCards());
		for(VotingCard votingCard : votingCards){
			Set<VotingSubcard> votingSubcards = new HashSet<VotingSubcard>(votingCard.getVotingSubcards());
			for(VotingSubcard votingSubcard : votingSubcards){
				Set<VotingSubcardOption> votingSubcardOptions = new HashSet<VotingSubcardOption>(votingSubcard.getVotingSubcardOptions());
				for(VotingSubcardOption votingSubcardOption : votingSubcardOptions){
					Set<Vote> votes = new HashSet<Vote>(votingSubcardOption.getVotes());
					for(Vote vote : votes){
						votesPackage = vote.getVotesPackage();
						if (!votesPackages.contains(votesPackage))
							votesPackages.add(votesPackage);
						vote.removeFromVotingSubcardOption(votingSubcardOption);
						session.delete(vote);
					}
					session.update(votingSubcardOption);
				}
			}
		}
		@SuppressWarnings("unchecked")
		ArrayList<Vote> votes = (ArrayList<Vote>) session
				.createCriteria(Vote.class)
				.add(Restrictions.like("electionName", electionName)).list();
		if (!votes.isEmpty()) {
			for(Vote vote : votes){
				votesPackage = vote.getVotesPackage();
				if (!votesPackages.contains(votesPackage))
					votesPackages.add(votesPackage);
				session.delete(vote);
			}
		}
		ArrayList<VotesPackage> votesPackages2 = new ArrayList<VotesPackage>(votesPackages);
		for (VotesPackage votesPackage2 : votesPackages2){
			session.delete(votesPackage2);
		}
		
		SummaryPackage summaryPackage = election.getSummaryPackage();
		if (summaryPackage != null){
			summaryPackage = (SummaryPackage) session.get(SummaryPackage.class, summaryPackage.getId());
			Set<OKWElectionResult> okwElectionResults = summaryPackage.getOkwElectionResults();
			ArrayList<OKWElectionResult> tmpOkwElectionResults = new ArrayList<OKWElectionResult>(okwElectionResults);
			for (OKWElectionResult okwElectionResult : tmpOkwElectionResults) {
				okwElectionResult.removeFromSummaryPackage(summaryPackage);			
				session.delete(okwElectionResult);
			}
			summaryPackage.removeFromElection(election);
			session.delete(summaryPackage);
		}
		
		session.getTransaction().commit();
		deleteElectionData(election.getId());
		logger.getLoggerInstance().log(Level.FINE, "Usunięcie wyborów Election: "+electionName);
	}
	
	public ArrayList<VotingCardCore> getVotingCardsToSend(Election election){
		ArrayList<VotingCardCore> votingCardCores = new ArrayList<VotingCardCore>();
		
		for(VotingCard votingCard : election.getVotingCards()){
			VotingCardCore votingCardCore = new VotingCardCore(votingCard.getName(), votingCard.getDescription());
			for (VotingSubcard votingSubcard : votingCard.getVotingSubcards()){
				VotingSubcardCore votingSubcardCore = new VotingSubcardCore(votingSubcard.getName(), votingSubcard.getDescription(), votingSubcard.getAllowedChecks());
				votingSubcard = get(VotingSubcard.class, votingSubcard.getId());
				for (VotingSubcardOption votingSubcardOption : votingSubcard.getVotingSubcardOptions()){
					VotingSubcardOptionCore votingSubcardOptionCore = new VotingSubcardOptionCore(votingSubcardOption.getName(), votingSubcardOption.getCkwVotingSubcardOption());
					votingSubcardCore.getVotingSubcardOptions().add(votingSubcardOptionCore);
				}
				votingCardCore.getVotingSubcards().add(votingSubcardCore);
			}
			votingCardCores.add(votingCardCore);
		}
		
		return votingCardCores;
	}
	
	public Timestamp getCurrentTime(){
		Calendar cal = Calendar.getInstance();
    	return new Timestamp(cal.getTime().getTime());
	}
	
	public Boolean saveVotes(String tokenValue, VoteCore voteCore){
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		Token token = (Token) session
				.createCriteria(Token.class)
				.add(Restrictions.like("value", tokenValue)).uniqueResult();
		if (token != null) {
			if (!voteCore.getCkwVotingSubcardOptions().isEmpty()) {
				Timestamp voteTime = getCurrentTime();
				Vote vote = new Vote(voteTime);
				Election election = (Election) session.get(Election.class, MainWindowO.electionNr);			
				vote.setElectionName(election.getName());
				Timestamp endTime = new Timestamp(election.getActualStartDate().getTime() + (election.getEndDate().getTime() - election.getStartDate().getTime()));
				if (voteTime.after(endTime))
					vote.setAfterEndTime(true);
				session.save(vote);
				
				for (Long ckwVotingSubcardOption : voteCore.getCkwVotingSubcardOptions()){
					VotingSubcardOption votingSubcardOption = (VotingSubcardOption) session
							.createCriteria(VotingSubcardOption.class)
							.add(Restrictions.like("ckwVotingSubcardOption", ckwVotingSubcardOption)).uniqueResult();
					vote.addToVotingSubcardOption(votingSubcardOption);
					session.update(vote);
					session.update(votingSubcardOption);
				}
			}
			logger.getLoggerInstance().log(Level.FINE, "Zapisanie głosu przy użyciu tokena: "+tokenValue);
			session.delete(token);
			session.getTransaction().commit();
			return true;
		} else {
			session.getTransaction().commit();
			return false;
		}
	}		

	public Long getSelectedElectionId(String administratorTokenValue){
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		Long electionId;

		AdministratorToken token = (AdministratorToken) session
				.createCriteria(AdministratorToken.class)
				.add(Restrictions.like("value", administratorTokenValue)).uniqueResult();
		session.getTransaction().commit();	
		
		if (token != null){
			electionId = token.getElection().getId();
			return electionId;
		}
		return null;
	}
	
	public Boolean checkIfProperToken(String administratorTokenValue) {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		
		AdministratorToken administratorToken = (AdministratorToken) session
				.createCriteria(AdministratorToken.class)
				.add(Restrictions.like("value", administratorTokenValue)).uniqueResult();
		if (administratorToken == null) {
			session.getTransaction().commit();
			return null;
		}
		
		Election election = (Election) session
				.createCriteria(Election.class)
				.add(Restrictions.like("status", 1)).uniqueResult();
		
		if (election == null) {
			session.getTransaction().commit();
			return true;
		} else {
			AdministratorToken administratorToken2 = (AdministratorToken) session
					.createCriteria(AdministratorToken.class)
					.add(Restrictions.like("election", election))
					.add(Restrictions.like("value", administratorTokenValue)).uniqueResult();
			session.getTransaction().commit();
			if (administratorToken2 != null)
				return true;
			else
				return false;
		}	
	}
	
	public VotesPackageCore getVotes(){ 
		ArrayList<VoteCore> voteCores = new ArrayList<VoteCore>();
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
	
		@SuppressWarnings("unchecked")
		ArrayList<Vote> votes = (ArrayList<Vote>) session
				.createCriteria(Vote.class)
				.add(Restrictions.isNull("votesPackage")).list();
		
		OKWConfiguration configuration = (OKWConfiguration) session
				.createCriteria(OKWConfiguration.class).uniqueResult();

		if (!votes.isEmpty()){
			VotesPackage votesPackage = new VotesPackage(((Election)session.get(Election.class, MainWindowO.electionNr)).getName()+"_"+configuration.getIdentificationField()+"_"+getCurrentTime());
			session.save(votesPackage);
			VotesPackageCore votesPackageCore = new VotesPackageCore(votesPackage.getName());
			for(Vote vote : votes){
				VoteCore voteCore = new VoteCore(vote.getCreatedTime());
				voteCore.setAfterEndTime(vote.getAfterEndTime());
				voteCore.setElectionName(vote.getElectionName());
				for (VotingSubcardOption votingSubcardOption : vote.getVotingSubcardOptions()){
					votingSubcardOption = (VotingSubcardOption) session.get(VotingSubcardOption.class, votingSubcardOption.getId());
					voteCore.getCkwVotingSubcardOptions().add(votingSubcardOption.getCkwVotingSubcardOption());
				}
				voteCores.add(voteCore);
				vote.setVotesPackage(votesPackage);
				session.update(vote);
			}
			votesPackageCore.setVoteCores(voteCores);
			
			session.getTransaction().commit();
			return votesPackageCore;
		} else {
			session.getTransaction().commit();
			return null;
		}
	}
	
	public void setVotesPackageAsSend(String packageName){
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		
		VotesPackage votesPackage = (VotesPackage) session
				.createCriteria(VotesPackage.class)
				.add(Restrictions.like("name", packageName)).uniqueResult();
		
		if (votesPackage != null){
			votesPackage.setIsSend(true);
			session.update(votesPackage);
		}
		
		session.getTransaction().commit();
	}
	
	public ArrayList<VotesPackageCore> getUnsendVotesPackages() {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		
		ArrayList<VotesPackageCore> votesPackageCores = new ArrayList<VotesPackageCore>();
		
		@SuppressWarnings("unchecked")
		ArrayList<VotesPackage> votesPackages = (ArrayList<VotesPackage>) session
				.createCriteria(VotesPackage.class)
				.add(Restrictions.like("isSend", false)).list();
		
		if (!votesPackages.isEmpty()) {
			for (VotesPackage votesPackage : votesPackages){
				@SuppressWarnings("unchecked")
				ArrayList<Vote> votes = (ArrayList<Vote>) session
						.createCriteria(Vote.class)
						.add(Restrictions.like("votesPackage", votesPackage)).list();
				
				if (!votes.isEmpty()){
					ArrayList<VoteCore> voteCores = new ArrayList<VoteCore>();
					VotesPackageCore votesPackageCore = new VotesPackageCore(votesPackage.getName());
					for(Vote vote : votes){
						VoteCore voteCore = new VoteCore(vote.getCreatedTime());
						for (VotingSubcardOption votingSubcardOption : vote.getVotingSubcardOptions()){
							votingSubcardOption = (VotingSubcardOption) session.get(VotingSubcardOption.class, votingSubcardOption.getId());
							voteCore.getCkwVotingSubcardOptions().add(votingSubcardOption.getCkwVotingSubcardOption());
						}
						voteCores.add(voteCore);
					}
					votesPackageCore.setVoteCores(voteCores);
					votesPackageCores.add(votesPackageCore);
				}	
			}
			session.getTransaction().commit();
			return votesPackageCores;
		} else {
			session.getTransaction().commit();
			return null;
		}
	}
	
	public Boolean canSavaElectionData(String electionName) {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		
		Election election = (Election) session
				.createCriteria(Election.class)
				.add(Restrictions.like("name", electionName)).uniqueResult();
		
		session.getTransaction().commit();
		
		if (election == null){
			return true;
		} else {
			 if (election.getStatus() == 0)
				 return true;
			 else 
				 return false;
		}
	}
	
	public void clearDatabase(Boolean deleteConfiguration) {
		ArrayList<Election> elections = (ArrayList<Election>) getAll(Election.class);
		for (Election election : elections)
			deleteElection(election.getName());
		deleteTable(State.class);
		deleteTable(Message.class);
		deleteTable(Vote.class);
		deleteTable(VotesPackage.class);
		deleteTable(Token.class);
		if(deleteConfiguration){
			deleteOKWConfiguration();
			deleteTable(Terminal.class);
			deleteAllTerminalConfigurations();
		}
		if (deleteConfiguration)
			logger.getLoggerInstance().log(Level.FINE, "Wyczyszczenie bazy razem z konfiguracją");
		else
			logger.getLoggerInstance().log(Level.FINE, "Wyczyszczenie bazy");
	}
	
	public void deleteOKWConfiguration(){
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		
		OKWConfiguration okwConfiguration = (OKWConfiguration) session
				.createCriteria(OKWConfiguration.class).uniqueResult();
		
		if (okwConfiguration != null){
			ConfigurationManager cm = ConfigurationManager.getInstance();
			cm.removeConfig(cm.getMyConfigurationFolderName(), cm.getMyConfigurationFolderName());
			session.delete(okwConfiguration);
		}
		
		session.getTransaction().commit();
	}
	
	public void deleteAllTerminalConfigurations(){
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		ConfigurationManager cm = ConfigurationManager.getInstance();
		
		@SuppressWarnings("unchecked")
		ArrayList<TerminalConfiguration> terminalConfigurations = (ArrayList<TerminalConfiguration>) session
				.createCriteria(TerminalConfiguration.class).list();
		
		for (TerminalConfiguration terminalConfiguration : terminalConfigurations) {
			cm.removeConfig(terminalConfiguration.getIdentificationField());
			session.delete(terminalConfiguration);
		}
		
		session.getTransaction().commit();
	}
	
	public Voter getVoter(String identificationField){
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		
		Election election = (Election) session.get(Election.class, MainWindowO.electionNr);
		Voter voter = (Voter) session
				.createCriteria(Voter.class)
				.add(Restrictions.like("identificationField", identificationField))
				.add(Restrictions.like("election", election)).uniqueResult();
		session.getTransaction().commit();
		
		return voter;
	}

	public void prepareDatabase(){ 
		deleteTable(Token.class);
		deleteTable(State.class);
		deleteTable(Message.class);
		logger.getLoggerInstance().log(Level.FINE, "Przygotowanie bazy pod wybory");
	}
	
	public SummaryPackageCore getSummaryPackage(){	
		if(MainWindowO.stanO.isKonczenieGlosowania()){
			for (okw.network.Terminal terminal : MainWindowO.cm.getTerminale()) {
				if(terminal.getStan()!= null)
					if (!terminal.getStan().isGlosowanieZakonczone() && terminal.getSocket()!=null){
						return null;
					}
						
			}
		} else
			return null;
		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		
		Election electionTmp = (Election) session.get(Election.class, MainWindowO.electionNr);
		electionTmp.setStatus(3);
		electionTmp.setActualEndDate(getCurrentTime());
		session.update(electionTmp);
		
		Election election = (Election) session
				.createCriteria(Election.class)
				.add(Restrictions.like("status", 3))
				.add(Restrictions.isNull("summaryPackage")).uniqueResult();
		
		if (election != null) {
			SummaryPackage summaryPackage = new SummaryPackage();
			int n = 0;
			for (Voter voter : election.getVoters())
				if (voter.getHasVoted())
					n++;
			summaryPackage.setVotesNumber(n);
			@SuppressWarnings("unchecked")
			ArrayList<Vote> votes = (ArrayList<Vote>) session
					.createCriteria(Vote.class)
					.add(Restrictions.like("electionName", election.getName())).list();
			
			@SuppressWarnings("unchecked")
			ArrayList<Vote> votesAfter = (ArrayList<Vote>) session
					.createCriteria(Vote.class)
					.add(Restrictions.like("electionName", election.getName()))
					.add(Restrictions.like("afterEndTime", true)).list();
			
			summaryPackage.setProperVotesNumber(votes.size());
			summaryPackage.setAfterTimeVotesNumber(votesAfter.size());
			summaryPackage.setActualStartDate(election.getActualStartDate());
			summaryPackage.setActualEndDate(election.getActualEndDate());
			
			session.save(summaryPackage);		
			for (VotingCard votingCard : election.getVotingCards()) {
				votingCard = (VotingCard) session.get(VotingCard.class, votingCard.getId());
				for (VotingSubcard votingSubcard : votingCard.getVotingSubcards()){
					votingSubcard = (VotingSubcard) session.get(VotingSubcard.class, votingSubcard.getId());
					for (VotingSubcardOption votingSubcardOption : votingSubcard.getVotingSubcardOptions()) {
						votingSubcardOption = (VotingSubcardOption) session.get(VotingSubcardOption.class, votingSubcardOption.getId());
						OKWElectionResult okwElectionResult = new OKWElectionResult(votingSubcardOption.getCkwVotingSubcardOption(), votingSubcardOption.getVotes().size());
						okwElectionResult.setSummaryPackage(summaryPackage);
						session.save(okwElectionResult);
						summaryPackage.getOkwElectionResults().add(okwElectionResult);						
					}
				}
			}
			session.update(summaryPackage);
			election.setSummaryPackage(summaryPackage);
			session.update(election);
			session.getTransaction().commit();
			logger.getLoggerInstance().log(Level.FINE, "Utworzenie paczki podsumowującej");
			return 	getSummaryPackageCore(summaryPackage);	
		} else {
			SummaryPackage summaryPackage = (SummaryPackage) session
					.createCriteria(SummaryPackage.class)
					.add(Restrictions.like("isSend", false)).uniqueResult();
			session.getTransaction().commit();
			if (summaryPackage != null) {
				
				return getSummaryPackageCore(summaryPackage);
			} else {
				return null;
			}
		}	
	}
	
	public SummaryPackageCore getSummaryPackageCore(SummaryPackage summaryPackage) {
		SummaryPackageCore summaryPackageCore = new SummaryPackageCore();
		summaryPackageCore.setVotesNumber(summaryPackage.getVotesNumber());
		summaryPackageCore.setProperVotesNumber(summaryPackage.getProperVotesNumber());
		summaryPackageCore.setAfterTimeVotesNumber(summaryPackage.getAfterTimeVotesNumber());
		summaryPackageCore.setActualStartDate(summaryPackage.getActualStartDate());
		summaryPackageCore.setActualEndDate(summaryPackage.getActualEndDate());
		for (OKWElectionResult okwElectionResult : summaryPackage.getOkwElectionResults()) {
			okwElectionResult = get(OKWElectionResult.class, okwElectionResult.getId());
			OKWElectionResultCore okwElectionResultCore = new OKWElectionResultCore(okwElectionResult.getCkwVotingSubcardOption(), okwElectionResult.getVotesNumber());
			summaryPackageCore.getOkwElectionResults().add(okwElectionResultCore);
		}
	
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		
		Election election = (Election) session
				.createCriteria(Election.class)
				.add(Restrictions.like("summaryPackage", summaryPackage)).uniqueResult();
		if (election == null){
			return null;
		}
		summaryPackageCore.setElectionName(election.getName());
		if (election != null) {
			@SuppressWarnings("unchecked")
			ArrayList<Voter> voters = (ArrayList<Voter>) session
					.createCriteria(Voter.class)
					.add(Restrictions.like("election", election))
					.add(Restrictions.like("hasVoted", true)).list();
			for (Voter voter : voters)
				summaryPackageCore.getVotersIdentificationFields().add(voter.getIdentificationField());
		}
		
		session.getTransaction().commit();
		logger.getLoggerInstance().log(Level.FINE, "Utworzenie paczki podsumowującej");
		return summaryPackageCore;
	}

	public void setSummaryPackageAsSend(String electionName){
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		
		Election election = (Election) session
				.createCriteria(Election.class)
				.add(Restrictions.like("name", electionName)).uniqueResult();
		
		SummaryPackage summaryPackage = election.getSummaryPackage();
		summaryPackage = (SummaryPackage) session.get(SummaryPackage.class, summaryPackage.getId());
		summaryPackage.setIsSend(true);
		
		session.update(summaryPackage);
		
		session.getTransaction().commit();
	}
}
